# -*- coding: utf-8 -*-

#   This file is part of deckbuilder.
#
#    DeckBuilder is free software; you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation; either version 2 of the License, or
#    (at your option) any later version.
#
#    DeckBuilder is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with deckbuilder; if not, write to the Free Software
#    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

import sys, os, wx
from xml.dom import minidom
from sqlite3 import dbapi2
import mainform, gamecard, settings, skin, language, deck, xmlhandler, network, gameframe, dialogs
 
# Classe engine
class Engine():

    #Metodo principale dell'applicazione
    def __init__(self):
        #TODO: Implementare splash screen
        self.Application = wx.App() #Inizializzo l'applicazione
        #Inizializzo delle variabili contenenti le path delle varie directory
        self.BaseDirectory = os.path.dirname(os.path.realpath(__file__)) #BaseDirectory
        #self.BaseDirectory = '/home/mazzo/Projects/deckbuilder/src/' #Base 
        self.SkinsDirectory = os.path.join(self.BaseDirectory, 'Skins') #Skins Directory
        self.LanguagesDirectory = os.path.join(self.BaseDirectory, 'Languages') #Languages Directory
        self.DecksDirectory = os.path.join(self.BaseDirectory, 'Decks') #Decks Directory
        self.ImagesDirectory = os.path.join(self.BaseDirectory, 'Images') #Images Directory
        #Creo le directory se non esistono
        if not os.path.exists(self.SkinsDirectory):
            os.mkdir(self.SkinsDirectory)
        if not os.path.exists(self.LanguagesDirectory):
            os.mkdir(self.LanguagesDirectory)
        if not os.path.exists(self.DecksDirectory):
            os.mkdir(self.DecksDirectory)
        if not os.path.exists(self.ImagesDirectory):
            os.mkdir(self.ImagesDirectory)
        self.Settings = settings.LoadSettings() #Carico le impostazioni
        self.Skins = skin.LoadSkins(self.SkinsDirectory) #Carico le ski
        self.Languages = language.LoadLanguages(self.LanguagesDirectory)
        self.Deck = deck.Deck()
        self.DeckPath = ''
        self.DatabaseCardsCount = len(self.GetAllCards())
        self.Frame = mainform.MainFrame(engine=self, parent=None, title="DeckBuilder",size=(800,600)) #Inizializzo il frame
        #self.Network = network.Network(self.Frame) #Inizializzo il network
        self.Network = ''
        self.Frame.Show() #Mostro il frame
        #self.GameFrame = gameframe.GameFrame(self)
        self.Application.MainLoop() #Loop dell'applicazione

    #Metodo che ritorna una carta dato il suo codice
    def FindCardByCode(self, code):
        con = dbapi2.connect(os.path.join(sys.path[0], 'cards.db')) #Mi connetto al db
        c = con.cursor() #Creo un oggetto cursor
        c.execute('SELECT * FROM cards WHERE code="'+code+'"') #Eseguo la query
        row = c.fetchone() #Ottengo i valori trovati
        card = gamecard.GameCard(row[0],row[1],row[2],row[3],row[4],row[5],row[6],row[7],row[8]) #Creo la carta
        return card

    #Metodo che ritorna una lista di carte data parte del suo nome
    def FindCardByNameLike(self, name):
        con = dbapi2.connect(os.path.join(sys.path[0], 'cards.db')) #Mi connetto al db
        c = con.cursor() #Creo un oggetto cursor
        c.execute('SELECT * FROM cards WHERE name LIKE "%'+name+'%"') #Eseguo la query
        data = c.fetchall() #Ottengo tutti i valori trovati
        li = list() #Creo la lista che conterra' le carte
        for row in data:
            card = gamecard.GameCard(row[0],row[1],row[2],row[3],row[4],row[5],row[6],row[7],row[8]) #Creo la carta
            li.append(card) #Aggiungo alla lista ogni carta
        return li

    def FindCardByName(self, name):
        con = dbapi2.connect(os.path.join(sys.path[0], 'cards.db')) #Mi connetto al db
        c = con.cursor() #Creo un oggetto cursor
        c.execute('SELECT * FROM cards WHERE name="'+name+'"') #Eseguo la query
        row = c.fetchone() #Ottengo i valori trovati
        card = gamecard.GameCard(row[0],row[1],row[2],row[3],row[4],row[5],row[6],row[7],row[8]) #Creo la carta
        return card
    
    def AdvancedSearch(self, name, type, attribute, stars, type2, atk, df, effect):
        con = dbapi2.connect(os.path.join(sys.path[0], 'cards.db')) #Mi connetto al db
        c = con.cursor() #Creo un oggetto cursor
        SQLCode = ''
        if name != '':
            if SQLCode == '':
                SQLCode = 'SELECT * FROM cards WHERE name LIKE %"%s"%' % name
            else:
                SQLCode += ' AND name LIKE %"%s"%' % name
        if effect != '':
            if SQLCode == '':
                SQLCode = 'SELECT * FROM cards WHERE effect LIKE %"%s"%' % effect
            else:
                SQLCode = ' AND effect LIKE %"%s"%' % effect

    def GetAllCards(self):
        '''Metodo che ritorna la lista completa delle carte'''
        con = dbapi2.connect(os.path.join(sys.path[0], 'cards.db')) #Mi connetto al db
        c = con.cursor() #Creo un oggetto cursor
        c.execute('SELECT * FROM cards') #Eseguo la query
        data = c.fetchall() #Ottengo tutti i valori trovati
        li = list() #Creo la lista che conterra' le carte
        for row in data:
            card = gamecard.GameCard(row[0],row[1],row[2],row[3],row[4],row[5],row[6],row[7],row[8]) #Creo la carta
            li.append(card) #Aggiungo alla lista ogni carta
        return li

    def GetCardImage(self, c):
        if c.IsFaceDown():
            bmp = self.GetSkinImage('CardBack')
            if c.IsHorizontal():
                bmp = self.Rotate90Bitmap(bmp)
            return bmp
        att = c.GetCardAttribute()
        ty = c.GetCardType()
        if att != 'Spell' and att != 'Trap':# Scelgo lo sfondo adatto
            if ty.find('Fusion') > -1:
                b = self.ResizeBitmap(self.GetSkinImage('Fusion'), 60, 88)
            elif ty.find('Ritual') > -1:
                b = self.ResizeBitmap(self.GetSkinImage('Ritual'), 60, 88)
            elif ty.find('Token') > -1:
                b = self.ResizeBitmap(self.GetSkinImage('Token'), 60, 88)
            elif ty.find('Effect') > -1:
                b = self.ResizeBitmap(self.GetSkinImage('MonsterEffect'), 60, 88)
            else:
                b = self.ResizeBitmap(self.GetSkinImage('Monster'), 60, 88)
        elif att == 'Trap':
            b = self.ResizeBitmap(self.GetSkinImage('Trap'), 60, 88)
        elif att == 'Spell':
            b = self.ResizeBitmap(self.GetSkinImage('Spell'), 60, 88)
        bmp = self.GetImageCardScaled(c.GetCardName())
        if not bmp is -1:
            dc = wx.MemoryDC()
            dc.SelectObject(b)
            dc.DrawBitmap(bmp, 8, 19)
        if c.IsHorizontal():
            b = self.Rotate90Bitmap(b)
        return b

    def GetBigCardImage(self, c):
        dc = wx.MemoryDC()
        
        if c.Attribute != 'Spell' and c.Attribute != 'Trap':# Scelgo lo sfondo adatto
            if c.Type.find('Fusion') > -1:
                BackSkin =self.GetSkinImage('Fusion')
            elif c.Type.find('Ritual') > -1:
                BackSkin = self.GetSkinImage('Ritual')
            elif c.Type.find('Token') > -1:
                BackSkin = self.GetSkinImage('Token')
            elif c.Type.find('Effect') > -1:
                BackSkin = self.GetSkinImage('MonsterEffect')
            else:
                BackSkin = self.GetSkinImage('Monster')
        if c.Attribute == 'Trap':
            BackSkin = self.GetSkinImage('Trap')
        if c.Attribute == 'Spell':
            BackSkin = self.GetSkinImage('Spell')
            
        dc.SelectObject(BackSkin) # Carico lo sfondo
        
        dc.SetFont(wx.Font(pointSize=8,family=wx.FONTFAMILY_DEFAULT,style=wx.FONTSTYLE_NORMAL,weight=wx.FONTWEIGHT_NORMAL,faceName='Tahoma'))
        dc.DrawText(c.Name[:21], 14,12)# Nome carta, limitato ai primi 20 caratteri
       
        if c.Attribute == 'Light':
            dc.DrawBitmap(self.GetSkinImage('LightIcon'), 110,11, True)
        if c.Attribute == 'Dark':
            dc.DrawBitmap(self.GetSkinImage('DarkIcon'), 110,11, True)
        if c.Attribute == 'Water':
            dc.DrawBitmap(self.GetSkinImage('WaterIcon'), 110,11, True)
        if c.Attribute == 'Fire':
            dc.DrawBitmap(self.GetSkinImage('FireIcon'), 110,11, True)
        if c.Attribute == 'Earth':
            dc.DrawBitmap(self.GetSkinImage('EarthIcon'), 110,11, True)
        if c.Attribute == 'Wind':
            dc.DrawBitmap(self.GetSkinImage('WindIcon'), 110,11, True)
        
        if c.Attribute != 'Trap' and c.Attribute != 'Spell':
            st = 0
            for stelline in range(0, int(c.Stars)):# Assegnazione stelle
                dc.DrawBitmap(self.GetSkinImage('Star'), 110 - st,28, True)
                st += 10
            
        if c.Attribute == 'Trap':
            dc.DrawBitmap(self.GetSkinImage('TrapIcon'), 110,11, True)
            if c.Type2.find('Continuous') > -1: 
                dc.DrawBitmap(self.GetSkinImage('ContinuousIcon'), 90,156, True)
            elif c.Type2.find('Counter') > -1:
                dc.DrawBitmap(self.GetSkinImage('CounterIcon'), 90,156, True)
                
        if c.Attribute == 'Spell':
            dc.DrawBitmap(self.GetSkinImage('SpellIcon'), 110,11)
            if c.Type2.find('Counter') > -1:
                dc.DrawBitmap(self.GetSkinImage('CounterIcon'), 90,156, True)
            elif c.Type2.find('Equip') > -1:
                dc.DrawBitmap(self.GetSkinImage('EquipIcon'), 90,156, True)
            elif c.Type2.find('Field') > -1:
                dc.DrawBitmap(self.GetSkinImage('FieldIcon'), 90,156, True)
            elif c.Type2.find('Ritual') > -1:
                dc.DrawBitmap(self.GetSkinImage('RitualIcon'), 90,156, True)
            elif c.Type2.find('Quick-Play') > -1:
                dc.DrawBitmap(self.GetSkinImage('Quick-PlayIcon'), 90,156, True)
            elif c.Type2.find('Continuous') > -1: 
                dc.DrawBitmap(self.GetSkinImage('ContinuousIcon'), 90,156, True)
        
        cbmp = self.GetImageCard(c.Name)
        if not cbmp is -1:
            dc.DrawBitmap(cbmp, 18, 43)
        
        return dc.GetAsBitmap()

    def ResizeBitmap(self, bmp, w, h, q=wx.IMAGE_QUALITY_HIGH):
        img = wx.ImageFromBitmap(bmp)
        img.Rescale(w, h, q)
        return wx.BitmapFromImage(img)
    
    def Rotate90Bitmap(self, bmp):
        img = wx.ImageFromBitmap(bmp)
        return wx.BitmapFromImage(img.Rotate90())

    def GetImageCardScaled(self, name):
        path = os.path.join(self.ImagesDirectory, name + '.jpg')
        if os.path.exists(path):
            image = wx.Image(path)
            image.Rescale(45, 45, wx.IMAGE_QUALITY_HIGH)
            return wx.BitmapFromImage(image)
        return -1

    def GetImageCard(self, name):
        path = os.path.join(self.ImagesDirectory, name + '.jpg')
        if os.path.exists(path):
            return wx.Bitmap(path)
        return -1

    def GetSkin(self): # Metodo che ritorna la skin usata
        key = self.GetSetting('Skin')
        if self.Skins.has_key(key):
            return self.Skins[key]
        else:
            return self.Skins['Default']

    def GetLang(self):
        key = self.GetSetting('Language')
        if self.Languages.has_key(key):
            return self.Languages[key]
        else:
            return self.Languages['English']

    def GetSkinImage(self,name): # Ritorna un immagine della skin data la sua key
         skin = self.GetSkin()
         if skin.Exists(name):
             return skin.GetImage(name)
         elif self.Skins['Default'].Exists(name):
             return self.Skins['Default'].GetImage(name)
         else:
             return -1

    def GetSetting(self,name):
        if self.Settings.has_key(name):
            return self.Settings[name]
        else:
            return -1

    def GetLangString(self,name):
        lang = self.GetLang()
        if lang.Exists(name):
            return lang.GetString(name)
        elif self.Languages['English'].Exists(name):
            return self.Languages['English'].GetString(name)
        else:
            return '?'

    def SaveDeck(self,deck,path):
        handle = open(path,'w')

        doc = minidom.Document()
        element = doc.createElement("deck")
        doc.appendChild(element)
        for c in deck.Cards:
            node = doc.createElement("card")
            node.setAttribute('code',c.Code)
            side = '0'
            if c.IsSide:
                side = '1'
            node.setAttribute('side',side)
            element.appendChild(node)
        data = doc.toxml()

        handle.write(data)
        handle.close()

    def OpenDeck(self,path):
        xmldoc = xmlhandler.LoadXml(path)
        self.Deck = deck.Deck()
        for node in xmldoc.firstChild.childNodes:
            c = self.FindCardByCode(node.getAttribute('code'))
            if node.getAttribute('side') == '1':
                c.IsSide = 1
            self.Deck.Add(c)

    def NewDeck(self):
        self.Deck = deck.Deck()
        self.DeckPath = ''

def ListDirs(path):
    '''Metodo che ritorna una lista contenente tute le directory trovate in <path>'''
    rd = os.listdir(path) # Ottengo la lista di file nel path dato
    dirs = [] # La lista che conterra' le directory
    for s in rd:
        dp = os.path.join(path,s) # Creo una stringa che rappresenta il path del file/directory
        if os.path.isdir(dp): # Testo se e' una directory
            dirs.append(dp) # La aggiungo alla lista
    return dirs # Ritorno la lista

def ListFiles(path):
    '''Metodo che ritorna una lista contenente tute i files trovati in <path>'''
    rd = os.listdir(path) # Ottengo la lista di file nel path dato
    files = [] # La lista che conterra' le directory
    for s in rd:
        dp = os.path.join(path,s) # Creo una stringa che rappresenta il path del file/directory
        if os.path.isfile(dp): # Testo se e' un file
            files.append(dp) # La aggiungo alla lista
    return files # Ritorno la lista

if __name__ == "__main__":
    e = Engine() # Richiamo il metodo principale dell'applicazione